home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / win_m_p / mews11.zip / MOUSE.C < prev    next >
C/C++ Source or Header  |  1991-11-10  |  16KB  |  658 lines

  1. /*    MOUSE.C:    Mouse functionality commands
  2.             for MicroEMACS 3.10
  3.             originally written by Dave G. Conroy
  4.             modified by Jeff Lomicka and Daniel Lawrence
  5. */
  6.  
  7. #include    <stdio.h>
  8. #include    "estruct.h"
  9. #include    "eproto.h"
  10. #include        "edef.h"
  11. #include    "elang.h"
  12.  
  13. #define    MNONE    0            /* Mouse commands.        */
  14. #define    MMOVE    1
  15. #define    MREG    2
  16. #define    MCREATE    3
  17. #define MDELETE    4
  18.  
  19. #if    MOUSE
  20. NOSHARE int    lastypos = HUGE;    /* Last mouse event row.    */
  21. NOSHARE int    lastxpos = HUGE;    /* Last mouse event column.    */
  22. NOSHARE int    lastmcmd = MNONE;    /* Last mouse command.        */
  23.  
  24. #if    WINDOW_TEXT
  25.  
  26. /* Redraw given screen and all screens behind it */
  27.  
  28. void PASCAL NEAR refresh_screen(sp)
  29.  
  30. SCREEN *sp;    /* screen image to refresh */
  31.  
  32. {
  33.     /* if we are suppressing redraws */
  34.     if (gflags & GFSDRAW)
  35.         return;
  36.  
  37.     /* at end of list, do nothing */
  38.     if (sp == (SCREEN *)NULL)
  39.         return;
  40.  
  41.     /* if first refresh, erase the page */
  42.     if (sp == first_screen) {
  43.         (*term.t_clrdesk)();
  44.         if (sp->s_next_screen == (SCREEN *)NULL)
  45.             sgarbf = TRUE;
  46.     }
  47.  
  48.     /* if there are others below, defer to them first */
  49.     if (sp->s_next_screen)
  50.         refresh_screen(sp->s_next_screen);
  51.  
  52.     select_screen(sp, FALSE);
  53.     update(TRUE);
  54. }
  55. #endif
  56.  
  57. /*
  58.  * Move mouse button, down. The window that the
  59.  * mouse is in is always selected (this lets you select a
  60.  * window by clicking anyplace in it, even off the end
  61.  * of the text). If the mouse points at text then dot is
  62.  * moved to that location.
  63.  */
  64. PASCAL NEAR movemd(f, n)
  65.  
  66. int f,n;    /* prefix flag and argument */
  67.  
  68. {
  69.     register WINDOW    *wp;
  70.     register WINDOW    *lastwp;
  71.     register LINE    *lp;
  72.  
  73.     /* make sure we are on the proper screen */
  74.     mouse_screen();
  75.  
  76.     /* adjust position by screen offset */
  77.     ypos -= term.t_roworg;
  78.     xpos -= term.t_colorg;
  79.  
  80.     /* if anything has changed, reset the click count */
  81.     if (lastmcmd != MMOVE || lastypos!=ypos || lastxpos!=xpos)
  82.         nclicks = 0;
  83.     ++nclicks;
  84.     lastwp = mousewindow(lastypos);        /* remember last window */
  85.  
  86.     /* reset the last position */
  87.     lastypos = ypos;
  88.     lastxpos = xpos;
  89.     lastmcmd = MMOVE;
  90.  
  91.     /* if we move the mouse off the windows, don't do anything with it */
  92.     if ((wp=mousewindow(ypos)) == NULL)
  93.         return(FALSE);
  94.  
  95.     /* if we are on the line with the point, adjust for extended lines */
  96.     if (wp == curwp && (lp = mouseline(wp, ypos)) == curwp->w_dotp)
  97.         xpos += lbound;
  98.  
  99.     /* make the window the mouse points to current */
  100.     curwp = wp;
  101.     curbp = wp->w_bufp;
  102.  
  103.     /* if we changed windows, update the modelines */
  104.     if (wp != lastwp)
  105.         upmode();
  106.  
  107.     /* if we aren't off the end of the text, move the point to the mouse */
  108.     if ((lp=mouseline(wp, ypos)) != NULL) {
  109.         curwp->w_dotp = lp;
  110.         curwp->w_doto = mouseoffset(wp, lp, xpos);
  111.     }
  112.  
  113.     return(TRUE);
  114. }
  115.  
  116.  
  117. /*    mouse-region-down:    mouse region operations
  118.  
  119.     nclicks = 0:    move cursor to mouse
  120.             set-mark
  121.  
  122.           1:    move cursor to mouse
  123.             kill-region
  124. */
  125.  
  126. PASCAL NEAR mregdown(f, n)
  127.  
  128. int f,n;    /* prefix flag and argument */
  129.  
  130. {
  131.     register WINDOW    *wp;
  132.     register WINDOW    *lastwp;
  133.     register LINE    *lp;
  134.     SCREEN *sp;
  135.     char scr_name[12];        /* constructed temp screen name */
  136.     static int temp_count = 0;    /* next temp screen number! */
  137.  
  138.     /* make sure we are on the proper screen */
  139.     mouse_screen();
  140.  
  141.     /* adjust position by screen offset */
  142.     ypos -= term.t_roworg;
  143.     xpos -= term.t_colorg;
  144.  
  145.     /* if anything has changed, reset the click count */
  146.     if (lastmcmd != MREG || lastypos != ypos || lastxpos != xpos)
  147.         nclicks = 0;
  148.     ++nclicks;
  149.     lastwp = mousewindow(lastypos);        /* remember last window */
  150.  
  151.     /* reset the last position */
  152.     lastypos = ypos;
  153.     lastxpos = xpos;
  154.     lastmcmd = MREG;
  155.  
  156. #if    !WINDOW_MSWIN
  157.     /* if we are in the upper left corner, create a new window */
  158.     if (xpos == 0 && ypos == 0) {
  159.  
  160.         /* get the name of the screen to create */
  161.         strcpy(scr_name, "SCREEN");
  162.         strcat(scr_name, int_asc(temp_count++));
  163.         while (lookup_screen(scr_name) != (SCREEN *)NULL) {
  164.             strcpy(scr_name, "SCREEN");
  165.             strcat(scr_name, int_asc(temp_count++));
  166.         }
  167.     
  168.         /* save the current dot position in the buffer info
  169.            so the new screen will start there! */
  170.         curbp->b_dotp = curwp->w_dotp;
  171.         curbp->b_doto = curwp->w_doto;
  172.  
  173.         /* screen does not exist, create it */
  174.         sp = init_screen(scr_name, curbp);
  175.     
  176.         /* and make this screen current */
  177.         return(select_screen(sp, TRUE));
  178.     }
  179. #endif
  180.  
  181.     /* if we move the mouse off the windows, don't move anything */
  182.     if ((wp=mousewindow(ypos)) == NULL)
  183.         return(FALSE);
  184.  
  185.     /* if we are on the line with the point, adjust for extended lines */
  186.     if (wp == curwp && (lp = mouseline(wp, ypos)) == curwp->w_dotp)
  187.         xpos += lbound;
  188.  
  189.     /* make the window the mouse points to current */
  190.     curwp = wp;
  191.     curbp = wp->w_bufp;
  192.  
  193.     /* if we changed windows, update the modelines */
  194.     if (wp != lastwp)
  195.         upmode();
  196.  
  197.     /* if we aren't off the end of the text, move the point to the mouse */
  198.     if ((lp=mouseline(wp, ypos)) != NULL) {
  199.         curwp->w_dotp = lp;
  200.         curwp->w_doto = mouseoffset(wp, lp, xpos);
  201.     }
  202.  
  203.     /* perform the region function */
  204.     if (nclicks == 1) {
  205.         return(setmark(FALSE, 0));
  206.     } else {
  207.         lastflag &= ~CFKILL;
  208.         return(killregion(FALSE, 0));
  209.     }
  210. }
  211.  
  212. /*    mouse-region-up:    mouse region operations
  213.  
  214.     If the corrosponding downclick was on a modeline, then we
  215.     wish to delete the indicated window. Otherwise we are using
  216.     this button to copy/paste.
  217.  
  218.     nclicks = 0:    move cursor to mouse
  219.             copy-region
  220.  
  221.           1:    move cursor to mouse
  222.             yank
  223.  
  224.           3:    reset nclicks to 0
  225. */
  226.  
  227. PASCAL NEAR mregup(f, n)
  228.  
  229. int f,n;    /* prefix flag and argument */
  230.  
  231. {
  232.     register WINDOW    *wp;
  233.     register WINDOW    *lastwp;
  234.     register LINE *lp;
  235.     register SCREEN *sp;        /* ptr to screen to delete */
  236.     register int lastmodeline;    /* was the dowbclick on a modeline? */
  237.     register int lastcmdline;    /* was the downclick on the command line? */
  238.  
  239.     /* adjust position by screen offset */
  240.     ypos -= term.t_roworg;
  241.     xpos -= term.t_colorg;
  242.  
  243.     /* if anything has changed, reset the click count */
  244.     if (lastmcmd != MREG || lastypos != ypos || lastxpos != xpos)
  245.         nclicks = 0;
  246.     ++nclicks;
  247.     lastwp = mousewindow(lastypos);        /* remember last window */
  248.  
  249. #if     !WINDOW_MSWIN
  250.     /* if the down click was in the upper left corner...
  251.        then we are moving a just created screen */
  252.     if (lastypos == 0 && lastxpos == 0) {
  253.         new_row_org(TRUE, ypos + term.t_roworg);
  254.         new_col_org(TRUE, xpos + term.t_colorg);
  255. #if    WINDOW_TEXT
  256.         refresh_screen(first_screen);
  257. #endif
  258.         return(TRUE);
  259.     }
  260. #endif
  261.  
  262.     /* Just where was the last click? */
  263.     lastmodeline = ismodeline(lastwp, lastypos);
  264.     lastcmdline = (lastypos == term.t_nrow);
  265.  
  266.     /* reset the last position */
  267.     lastypos = ypos;
  268.     lastxpos = xpos;
  269.     lastmcmd = MREG;
  270.  
  271.     /* if we started on a modeline.... */
  272.     if (lastmodeline)
  273.         return(delwind(TRUE, 0));
  274.  
  275.     /* if we are on a command line */
  276.     if (lastcmdline) {
  277.         if (ypos != term.t_nrow)
  278.  
  279.             /* ABORT ABORT ABORT screen deletion */
  280.             return(TRUE);
  281.         else {
  282.  
  283.             /* delete the screen last screen means exiting */
  284.             if (first_screen->s_next_screen == (SCREEN *)NULL)
  285.                 return(quit(FALSE, 0));
  286.  
  287.             /* bring the second last screen to front*/
  288.             sp = first_screen;
  289.             select_screen(sp->s_next_screen, FALSE);
  290.  
  291.             /* and dump the front screen */
  292.             first_screen->s_next_screen = sp->s_next_screen;
  293.             free_screen(sp);
  294. #if    WINDOW_TEXT
  295.             refresh_screen(first_screen);
  296. #endif
  297.             return(TRUE);
  298.         }
  299.     }
  300.  
  301.     /* if we move the mouse off the windows, don't move anything */
  302.     if ((wp=mousewindow(ypos)) == NULL)
  303.         return(FALSE);
  304.  
  305.     /* if we are on the line with the point, adjust for extended lines */
  306.     if (wp == curwp && (lp = mouseline(wp, ypos)) == curwp->w_dotp)
  307.         xpos += lbound;
  308.  
  309.     /* make the window the mouse points to current */
  310.     curwp = wp;
  311.     curbp = wp->w_bufp;
  312.  
  313.     /* if we aren't off the end of the text, move the point to the mouse */
  314.     if ((lp=mouseline(wp, ypos)) != NULL && nclicks < 3) {
  315.         curwp->w_dotp = lp;
  316.         curwp->w_doto = mouseoffset(wp, lp, xpos);
  317.     }
  318.  
  319.     /* if we changed windows, update the modelines, abort the new op */
  320.     if (wp != lastwp) {
  321.         upmode();
  322.         return(TRUE);
  323.     }
  324.  
  325.     /* perform the region function */
  326.     if (nclicks == 1) {
  327.         return(copyregion(FALSE, 0));
  328.     } else if (nclicks == 2) {
  329.         return(yank(FALSE, 1));
  330.     } else {
  331.         nclicks = 0;
  332.         return(TRUE);
  333.     }
  334. }
  335.  
  336. /*
  337.  * Move mouse button, up. The up click must be
  338.  * in the text region of a window. If the old click was in a
  339.  * mode line then the mode line moves to the row of the
  340.  * up click. If the old click is not in a mode line then the
  341.  * window scrolls. The code in this function is just
  342.  * too complex!
  343.  */
  344. PASCAL NEAR movemu(f, n)
  345.  
  346. int f,n;    /* prefix flag and argument */
  347.  
  348. {
  349.     register WINDOW    *lastwp;
  350.     register WINDOW    *wp;
  351.     register int lastmodeline;    /* was the downclick on a modeline? */
  352.     register int deltay;
  353.     register int deltax;
  354. #if    WINDOW_TEXT
  355.     register int redraw_needed;    /* is a screen redraw required */
  356. #endif
  357.  
  358.     /* adjust position by screen offset */
  359.     ypos -= term.t_roworg;
  360.     xpos -= term.t_colorg;
  361.  
  362.     /* no movement... fail the command */
  363.     if (lastypos==ypos && lastxpos==xpos)
  364.         return(FALSE);
  365.  
  366. #if     !WINDOW_MSWIN
  367.     /* if the down click was in the bottom right corner...
  368.        then we are resizing */
  369.     if (lastypos == term.t_nrow && lastxpos + 1 == term.t_ncol) {
  370. #if    WINDOW_TEXT
  371.         if (xpos < term.t_ncol || ypos < term.t_nrow)
  372.             redraw_needed = TRUE;
  373.         else
  374.             redraw_needed = FALSE;
  375. #endif
  376.         newwidth(TRUE, xpos + 1);
  377.         newsize(TRUE, ypos + 1);
  378. #if    WINDOW_TEXT
  379.         if (redraw_needed) {
  380.             refresh_screen(first_screen);
  381.         }
  382. #endif
  383.         return(TRUE);
  384.     }
  385.  
  386.     /* if the down click was in the upper left corner...
  387.        then we are moving the screen */
  388.     if (lastypos == 0 && lastxpos == 0) {
  389.         new_row_org(TRUE, ypos + term.t_roworg);
  390.         new_col_org(TRUE, xpos + term.t_colorg);
  391. #if    WINDOW_TEXT
  392.         refresh_screen(first_screen);
  393. #endif
  394.         return(TRUE);
  395.     }
  396. #endif
  397.  
  398.     /* if the down click was not in a window.. fail the command
  399.        (for example, if we click on the command line) */
  400.     if ((lastwp=mousewindow(lastypos)) == NULL)
  401.         return(FALSE);
  402.  
  403.     /* did we down click on a modeline? */
  404.     lastmodeline = ismodeline(lastwp, lastypos);
  405.  
  406.     /* are we not in a window? fail it then */
  407.     if ((wp=mousewindow(ypos)) == NULL)
  408.         return(FALSE);
  409.  
  410.     /* how far did we move? */
  411.     deltay = lastypos-ypos;
  412.     deltax = lastxpos-xpos;
  413.     lastypos = ypos;
  414.     lastxpos = xpos;
  415.  
  416.     /* if we started on a modeline.... */
  417.     if (lastmodeline) {
  418.  
  419.         /* move the window horizontally */
  420.         if (deltax != 0 && (diagflag || deltay == 0)) {
  421.             lastwp->w_fcol += deltax;
  422.             if (lastwp->w_fcol < 0)
  423.                 lastwp->w_fcol = 0;
  424.             lastwp->w_flag |= WFMODE|WFHARD;
  425.             if (deltay == 0)
  426.                 return(TRUE);
  427.         }
  428.  
  429.         /* don't allow the bottom modeline to move */
  430.         if (lastwp->w_wndp == NULL)
  431.             return(FALSE);
  432.  
  433.         /* shrink the current window */
  434.         if (deltay > 0) {
  435.             if (lastwp != wp)
  436.                 return(FALSE);
  437.             curwp = wp;
  438.             curbp = wp->w_bufp;
  439.             return(shrinkwind(TRUE, deltay));
  440.         }
  441.  
  442.         /* or grow it */
  443.         if (deltay < 0) {
  444.             if (wp != lastwp->w_wndp)
  445.                 return(FALSE);
  446.             curwp = lastwp;
  447.             curbp = lastwp->w_bufp;
  448.             return(enlargewind(TRUE, -deltay));
  449.         }
  450.     }
  451.  
  452.     /* did we up click in a modeline? fail it them */
  453.     if (ismodeline(wp, ypos) != FALSE)
  454.         return(FALSE);
  455.  
  456.     /* we can not move outside the current window */
  457.     if (lastwp != wp)
  458.         return(FALSE);
  459.  
  460.     /* move horizontally as well? */
  461.     if (deltax != 0 && (diagflag || deltay == 0)) {
  462.         wp->w_fcol += deltax;
  463.         if (wp->w_fcol < 0)
  464.             wp->w_fcol = 0;
  465.         wp->w_flag |= WFMODE;
  466.     }
  467.  
  468.     /* and move the screen */
  469.     return(mvdnwind(TRUE, deltay));
  470. }
  471.  
  472. /*
  473.  * Return a pointer to the WINDOW structure
  474.  * for the window in which "row" is located, or NULL
  475.  * if "row" isn't in any window. The mode line is
  476.  * considered to be part of the window.
  477.  */
  478.  
  479. WINDOW *PASCAL NEAR mousewindow(row)
  480.  
  481. register int    row;
  482.  
  483. {
  484.     register WINDOW    *wp;
  485.  
  486.     /* must be a positiove row! */
  487.     if (row < 0)
  488.         return(NULL);
  489.  
  490.     /* step through each window on the active screen */
  491.     wp = wheadp;
  492.     while (wp != NULL) {
  493.  
  494.         /* is this row within the current window? */
  495.         if (row < wp->w_ntrows+1)
  496.             return(wp);
  497.  
  498.         /* advance to the next window */
  499.         row -= wp->w_ntrows+1;
  500.         wp = wp->w_wndp;
  501.     }
  502.     return(NULL);
  503. }
  504.  
  505. /*
  506.  * The row "row" is a row within the window
  507.  * whose WINDOW structure is pointed to by the "wp"
  508.  * argument. Find the associated line, and return a pointer
  509.  * to it. Return NULL if the mouse is on the mode line,
  510.  * or if the mouse is pointed off the end of the
  511.  * text in the buffer.
  512.  */
  513.  
  514. LINE *PASCAL NEAR mouseline(wp, row)
  515.  
  516. register WINDOW    *wp;
  517. register int    row;
  518.  
  519. {
  520.     register LINE    *lp;
  521.  
  522.     row -= wp->w_toprow;
  523.     if (row >= wp->w_ntrows + (modeflag ? 0 : 1))
  524.         return(NULL);
  525.     lp = wp->w_linep;
  526.     while (row--) {
  527.         if (lp == wp->w_bufp->b_linep)    /* Hit the end.        */
  528.             return(NULL);
  529.         lp = lforw(lp);
  530.     }
  531.     return(lp);
  532. }
  533.  
  534. /*
  535.  * Return the best character offset to use
  536.  * to describe column "col", as viewed from the line whose
  537.  * LINE structure is pointed to by "lp".
  538.  */
  539.  
  540. PASCAL NEAR mouseoffset(wp, lp, col)
  541.  
  542. register WINDOW *wp;
  543. register LINE    *lp;
  544. register int    col;
  545.  
  546. {
  547.     register int    c;
  548.     register int    offset;
  549.     register int    curcol;
  550.     register int    newcol;
  551.  
  552.     offset = 0;
  553.     curcol = 0;
  554.     col += wp->w_fcol;    /* adjust for extended lines */
  555.     while (offset != llength(lp)) {
  556.         newcol = curcol;
  557.         if ((c=lgetc(lp, offset)) == '\t')
  558.             newcol += -(newcol % tabsize) + (tabsize - 1);
  559.         else if (c<32)    /* ISCTRL */
  560.             ++newcol;
  561.         ++newcol;
  562.         if (newcol > col)
  563.             break;
  564.         curcol = newcol;
  565.         ++offset;
  566.     }
  567.     return(offset);
  568. }
  569.  
  570. PASCAL NEAR mouse_screen()
  571.  
  572. {
  573.     register SCREEN *screen_ptr;    /* screen to test mouse in */
  574.  
  575.     /* if we move the mouse off the windows, check for other windows */
  576.     if ((ypos < term.t_roworg) || (xpos < term.t_colorg) ||
  577.         (ypos > term.t_roworg + term.t_nrow) ||
  578.         (xpos >= term.t_colorg + term.t_ncol)) {
  579.  
  580.         /* scan through the other windows */
  581.         screen_ptr = first_screen->s_next_screen;
  582.         while (screen_ptr != (SCREEN *)NULL) {
  583.  
  584.             /* is the mouse in this window? */
  585.             if ((ypos >= screen_ptr->s_roworg) &&
  586.                 (xpos >= screen_ptr->s_colorg) &&
  587.                 (ypos <= screen_ptr->s_roworg + screen_ptr->s_nrow) &&
  588.                 (xpos <= screen_ptr->s_colorg + screen_ptr->s_ncol)) {
  589.  
  590.                 /* select this screen */
  591.                 select_screen(screen_ptr, FALSE);
  592.                 lastxpos = -1;
  593.                 lastypos = -1;
  594.                 break;
  595.             }
  596.  
  597.             /* on to the next screen */
  598.             screen_ptr = screen_ptr->s_next_screen;
  599.         }
  600.     }
  601. }
  602.  
  603. PASCAL NEAR ismodeline(wp, row)
  604.  
  605. WINDOW    *wp;
  606. int row;
  607.  
  608. {
  609.     if (row == wp->w_toprow+wp->w_ntrows && modeflag)
  610.         return(TRUE);
  611.     return(FALSE);
  612. }
  613.  
  614. /* The mouse has been used to resize the physical window. Now we need to
  615.    let emacs know about the newsize, and have him force a re-draw
  616. */
  617.  
  618. PASCAL NEAR resizm(f, n)
  619.  
  620. int f, n;    /* these are ignored... we get the new size info from
  621.            the mouse driver */
  622. {
  623. #if    WINDOW_TEXT
  624.     register int redraw_needed;    /* is a screen redraw required */
  625. #endif
  626.  
  627.     /* make sure we are on the proper screen */
  628.     mouse_screen();
  629.  
  630.     /* adjust position by screen offset */
  631.     ypos -= term.t_roworg;
  632.     xpos -= term.t_colorg;
  633.  
  634. #if    WINDOW_TEXT
  635.         if (xpos < term.t_ncol || ypos < term.t_nrow)
  636.             redraw_needed = TRUE;
  637.         else
  638.             redraw_needed = FALSE;
  639. #endif
  640.  
  641.     /* change to the new size */
  642.     newwidth(TRUE, xpos + 1);
  643.     newsize(TRUE, ypos + 1);
  644.  
  645. #if    WINDOW_TEXT
  646.     if (redraw_needed) {
  647.         refresh_screen(first_screen);
  648.     }
  649. #endif
  650.     return(TRUE);
  651. }
  652.  
  653. #else
  654. mousehello()
  655. {
  656. }
  657. #endif
  658.